package model

import (
	"errors"
	"gorm.io/gorm"
	"iot-base/auth/utils"
	"time"
)

type (
	AuthGroupModel struct {
		db *gorm.DB
	}

	AuthGroup struct {
		Model
		Pid       int64  `gorm:"index;default:0" gorm:"comment:父ID" json:"pid"`
		GroupName string `gorm:"type:varchar(100)"gorm:"comment:权限组昵称" json:"group_name"`
		Path      string `gorm:"type:text;index"gorm:"comment:所有父级节点信息" json:"path"`
	}
)

func NewAuthGroupModel(db *gorm.DB) *AuthGroupModel {
	return &AuthGroupModel{
		db: db,
	}
}

func (m *AuthGroupModel) GetGroupsByid(id int64) (AuthGroup, error) {
	var authGroup AuthGroup
	err := m.db.Where("id = ?", id).First(&authGroup).Error
	return authGroup, err
}

func (m *AuthGroupModel) AddGroup(authGroup *AuthGroup) error {
	authGroup.ID = utils.GetUid()
	authGroup.CreatedAt = time.Now()
	authGroup.UpdatedAt = authGroup.CreatedAt
	return m.db.Create(authGroup).Error
}

func (m *AuthGroupModel) DelGroup(id int64) (int64, error) {
	result := m.db.Where("id = ?", id).Delete(&AuthGroup{})
	return result.RowsAffected, result.Error
}

// UpdateGroup 修改角色.
func (m *AuthGroupModel) UpdateGroup(id, pid int64, name, path string) (int64, error) {
	var group AuthGroup
	group.Pid = pid
	group.Path = path
	group.GroupName = name
	group.UpdatedAt = time.Now()
	result := m.db.Where("id = ?", id).Updates(group)
	return result.RowsAffected, result.Error
}

func (m *AuthGroupModel) FindGroupCount() (int64, error) {
	var count int64
	dbSession := m.db.Model(&AuthGroup{})
	err := dbSession.Count(&count).Error
	if err != nil {
		return count, err
	}
	return count, nil
}

func (m AuthGroupModel) FindGroup(page, size int) ([]AuthGroup, error) {
	group := make([]AuthGroup, 0, 10)
	err := m.db.Limit(size).Offset((page - 1) * size).Find(&group).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return group, nil
	} else if err != nil {
		return group, err
	}
	return group, nil
}

func (m AuthGroupModel) FindGroupByIds(ids string) ([]AuthGroup, error) {
	group := make([]AuthGroup, 0, 10)
	err := m.db.Where("id in (?)", ids).Find(&group).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return group, nil
	} else if err != nil {
		return group, err
	}
	return group, nil
}

func (m AuthGroupModel) FindAll() ([]AuthGroup, error) {
	group := make([]AuthGroup, 0, 1)
	err := m.db.Where("1=1").Find(&group).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return group, nil
	} else if err != nil {
		return group, err
	}
	return group, nil
}

// FindChildNode 查找子节点
func (m AuthGroupModel) FindChildNode(path string) ([]AuthGroup, error) {
	group := make([]AuthGroup, 0, 1)
	err := m.db.Where(" path like ?", path+"%").Find(&group).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return group, nil
	} else if err != nil {
		return group, err
	}
	return group, nil
}

// GetUserGroup 查询用户组.
func (m *AuthGroupModel) GetUserGroup(uid int64) ([]AuthGroup, error) {
	var group []AuthGroup
	err := m.db.Joins("JOIN user_groups ON user_groups.group_id = auth_groups.id AND user_groups.uid = ?", uid).Find(&group).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return group, nil
	} else if err != nil {
		return group, err
	}
	return group, nil
}

func (s AuthGroup) GetTitle() string {
	return s.GroupName
}
func (s AuthGroup) GetId() int64 {
	return s.ID
}
func (s AuthGroup) GetFatherId() int64 {
	return s.Pid
}
func (s AuthGroup) GetData() interface{} {
	return s
}
func (s AuthGroup) IsRoot() bool {
	// 这里通过FatherId等于0 或者 FatherId等于自身Id表示顶层根节点
	return s.Pid == 0 || s.Pid == s.ID
}

type GroupTrees []AuthGroup

// ConvertToINodeArray 将当前数组转换成父类 INode 接口 数组
func (s GroupTrees) ConvertToINodeArray() (nodes []utils.INode) {
	for _, v := range s {
		nodes = append(nodes, v)
	}
	return
}
